package com.tqz.rc.server.core;

import com.tqz.rc.api.BeatInfo;
import com.tqz.rc.api.Instance;
import com.tqz.rc.common.exception.RcException;
import com.tqz.rc.common.result.Result;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Map;

/**
 * <p>实例操作的实现类。
 *
 * @author tianqingzhao
 * @since 2021/8/26 13:57
 */
@org.springframework.stereotype.Service
public class InstanceOperatorImpl implements InstanceOperator {

    @Autowired
    private ServiceManager serviceManager;

    @Override
    public void registerInstance(String namespaceId, Instance instance) throws RcException {
        serviceManager.registerInstance(namespaceId, instance.getServiceName(), instance);
    }

    @Override
    public Map<String, Service> selectInsatnces(String namespaceId) {
        return serviceManager.chooseServiceMap(namespaceId);
    }

    @Override
    public List<Instance> selectInsatnces(String namespaceId, String serviceName, String groupName) {
        // 对于分组名称nacos采用的是在客户端进行处理，把所有的服务又在客户端存储到一个 `ServiceInfo` 中，
        // 该对象中包含服务名称、分组名称、集群名称、实例列表，
        // 而该对象存储在一个map中，map的key为 serviceName+groupName，value为 `ServiceInfo`。
        // 既然这样存储，那么服务端有实例变更的时候，应该会有事件或者http请求之类的操作通知客户端的其他实例的变更。
        Service service = serviceManager.getService(namespaceId, serviceName);
        return service.allIps(true);
    }

    @Override
    public int beat(String namespaceId, String serviceName, String clusterName, String ip, int port) {
        Service service = serviceManager.getService(namespaceId, serviceName);

        // 构建服务端处理心跳的对象
        BeatInfo beatInfo = new BeatInfo();
        beatInfo.setClusterName(clusterName);
        beatInfo.setIp(ip);
        beatInfo.setPort(port);

        // 处理客户端的心跳
        service.processClientBeat(beatInfo);

        return new Result<>().getCode();
    }
}
